#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

#define WORKER_NUM 3
#define TASK_NUM 5
#define BUF_SIZE 128

// 读取一行，处理管道粘包
ssize_t read_line(int fd, char *buf, size_t maxlen) {
    ssize_t n, rc;
    char c;
    for (n = 0; n < maxlen - 1; n++) {
        rc = read(fd, &c, 1);
        if (rc == 1) {
            if (c == '\n') {
                break; // 读到行尾
            }
            buf[n] = c;
        } else if (rc == 0) {
            if (n == 0) return 0; // EOF
            else break;
        } else {
            return -1; // read error
        }
    }
    buf[n] = '\0';
    return n;
}

int main()
{
    int pipes[WORKER_NUM][2];

    for (int i = 0; i < WORKER_NUM; i++)
    {
        if (pipe(pipes[i]) == -1)
        {
            perror("pipe");
            exit(1);
        }

        pid_t pid = fork();
        if (pid == 0)
        {
            // 子进程
            close(pipes[i][1]);  // 关闭写端
            char buf[BUF_SIZE];
            while (1)
            {
                ssize_t n = read_line(pipes[i][0], buf, sizeof(buf));
                if (n > 0)
                {
                    if (strcmp(buf, "exit") == 0)
                    {
                        printf("Worker %d exit.\n", getpid());
                        break;
                    }
                    printf("Worker %d processing: %s\n", getpid(), buf);
                    sleep(1); // 模拟耗时
                } else if (n == 0) {
                    // 管道关闭
                    break;
                } else {
                    perror("read");
                    break;
                }
            }
            close(pipes[i][0]);
            exit(0);
        }
        else if (pid > 0)
        {
            // 父进程
            close(pipes[i][0]);  // 关闭读端
        }
        else
        {
            perror("fork");
            exit(1);
        }
    }

    // 派发任务
    for (int t = 0; t < TASK_NUM; t++)
    {
        char task[64];
        sprintf(task, "task-%d\n", t);
        int worker_id = t % WORKER_NUM;
        write(pipes[worker_id][1], task, strlen(task));
    }

    // 发送 exit 信号给每个 worker
    for (int i = 0; i < WORKER_NUM; i++)
    {
        write(pipes[i][1], "exit\n", 5);
        close(pipes[i][1]);
    }

    // 等待所有子进程退出
    for (int i = 0; i < WORKER_NUM; i++)
    {
        wait(NULL);
    }

    printf("All workers exited, master done.\n");
    return 0;
}
